#ifdef MINIMUM_MEMORY
  #define MAX_TUPLEAGGR      3  // how many data values can be merged into one message
  #define MAX_JOINNODES     20  // max number of source and targets combined supported
  #define MAX_JOINPAIRS     20  // max number of pairs between sources and targets
  #define MAX_JOINWINDOWS   20
#else
  #define MAX_TUPLEAGGR      4
  #define MAX_JOINNODES     60
  #define MAX_JOINPAIRS    100
  #define MAX_JOINWINDOWS   60
#endif

#define EST_SENS(r)         (((r) == REL_J) ? 2 : 3)
#define EST_WINDOW           15
#define EST_RENORMALIZE      50

#define MIN_SEL              1   // minimum inv. selectivity (100% selective)
#define MAX_SEL            100   // maximum inv. selectivity (1% selective)

#define MAX_ESTTUPLECOUNT 65535u

#define PAIROPT_BASE         1
#define PAIROPT_INNET        2

typedef struct {                // structure of the window join buffer
  uint8_t used;

  ADDRESS node_id;              // source/target node
  uint8_t path_len;             // path to this source/target node
  ADDRESS *path;
} PACKING_MACRO QUERYJOIN_ENTRY;

typedef struct {
  uint8_t used;
  
  uint8_t query_id, rel_id, max_seq;
  uint8_t height, width;
  ATTRIBUTE *window;

  uint8_t node_index;
} PACKING_MACRO WINDOW_ENTRY;

typedef struct {
  uint8_t used;

  uint8_t window_index[SRCREL_COUNT];
  uint8_t options;

  uint8_t sel_est[REL_COUNT];
  uint16_t tuple_count[REL_COUNT];
  uint32_t start_time;
} PACKING_MACRO JOINPAIRS_ENTRY;

QUERYJOIN_ENTRY windowjoin_nodes[MAX_JOINNODES];
WINDOW_ENTRY windowjoin_windows[MAX_JOINWINDOWS];
JOINPAIRS_ENTRY windowjoin_pairs[MAX_JOINPAIRS];   // structure for maintaining source/target pairs

void init_mwindowjoin();

int add_joinpair(uint8_t query_id, ADDRESS node1, uint8_t path_len1, ADDRESS *path1, ADDRESS node2,
  uint8_t path_len2, ADDRESS *path2, uint8_t options);
void remove_joinpair(uint8_t query_id, ADDRESS node1, ADDRESS node2, uint8_t options, uint8_t confirm);
uint8_t place_tuple(uint8_t tuple_len, ATTRIBUTE *tuple);

void display_joinbuffer();

uint8_t windowjoin_resolvepath(ADDRESS dest_node, ADDRESS *next_hop, ADDRESS *path, uint8_t *path_len);

void update_windowjoin(QUERY_ENTRY *q);
void stopquery_windowjoin(QUERY_ENTRY *p);


